package models;


import akka.actor.*;
import static akka.pattern.Patterns.ask;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;

import play.libs.F.*;
import play.mvc.*;
import play.libs.*;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import play.Logger;

/** Class thread communication with one client. */
public class ServerConnection extends UntypedActor {

    protected WebSocket.In<JsonNode>  in;
    protected WebSocket.Out<JsonNode> out;
    /**data received from client.*/
   // private String dataIn;
    /**date sends from client.*/
   // private String dataOut;
    /** Server's Manager of Clients.*/
    private final ActorRef moc;
    /** Client's object */
    private Player client;
    /** If it's true, Thread ends listen the client. */
    private boolean end;
    
    private boolean startGame;

     /**constructor.
     * @param socket client's socket.
     * @param moc ManagerOfClients
     * @param Client client
     * @throws ServerException, when client's socket throws IOException.
     */
    public ServerConnection( WebSocket.In<JsonNode> _in,
            WebSocket.Out<JsonNode> _out,  ActorRef Moc, 
            final Player client) throws ServerException
     {
        this.client = client;
		this.moc = Moc;
		//this.dataIn = " ";
		//this.dataOut = " ";
		this.startGame = false; 
		this.end = false;
		this.in = _in;
		this.out = _out;
		System.out.println(this.client.getNumber()+"is conected");
		this.client.setConnection(this);
		
        in.onMessage(new Callback<JsonNode>()
        {
            @Override
            public void invoke(JsonNode event)
            {
                try
                {    
                	String comand = event.get("comand").asText();      
                	getSelf().tell(comand, getSelf() );
                	System.out.println(comand);            	
                }
                catch (Exception e)
                {
                    Logger.error("invokeError");
                }
              
            }
        });
        
        in.onClose(new Callback0()
        {
            @Override
            public void invoke()
            {
            	System.out.println("close");
                moc.tell(new Quit(client.getNick()), getSelf() );
            }
        });
	}
   /**constor for tmp connection 
     * @param socket client's socket.
     * @param moc ManagerOfClients
     * @throws ServerException, when client's socket throws IOException.
     */
   /* public ServerConnection(final Socket socket, final ManagerOfClients moc)
    {
       this.socket = socket;
		this.moc = moc;
		this.dataIn = " ";
		this.dataOut = " ";

		try
		{
			this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			this.out = new PrintWriter(socket.getOutputStream(), true);
		}
		catch(IOException e)
		{
			System.err.println("Input/Output error");
		}
		this.start();
	}*/
	
	public void end()
	{
		end = true;
	}
	/**Method allows send data to client from server
	 * @param data sends to client
	 * @param data, data sends to client */
	public void send( String data)
	{
		  ObjectNode event = Json.newObject();
          event.put("message", data); 
          
          out.write(event);
		}
	
	public void startGame()
	{
		startGame = true;
	}
	   @Override
	    public void preStart()
	    {        
	        String text = "my Actor is now running!";
	    	moc.tell(new Info(text, client.getNick()), getSelf()); 
	    }

	    @Override
	    public void postStop()
	    {
	        String text = "I've been killed";
	    	moc.tell(new Info(text, client.getNick()), getSelf()); 
	    }
	public void stopGame()
	{
		startGame = false;
	}
	public void endGame()
	{
		startGame = false;
	}
	/**method which executes the thread */
	/*public void run()
	{
		while(!end)
		{
			if(!this.socket.isConnected())
			{
				System.out.println("close");
				end = true;
				break;
			}
			try
			{
			if(dataOut.equals(" ") )
			{
				try{
					dataIn = in.readLine();
					System.out.println("read");
                }
				catch(IOException e)
				{
					this.client.run("Fold_");
					out.println("You_are_disconect");
					end = true;
				}
				if(dataIn == null)
				{
					out.println("You_are_disconect");
					System.out.println("Player diconeted");
					end = true;
					break;
				}
				//System.out.println(dataIn);
				this.execute();
				
			}
			//System.out.println("run"+dataOut);
			if(!dataOut.equals(" "))
			{
				out.println(dataOut);
				dataOut = " ";
			}
            dataIn = " ";
			
				this.sleep(10);
			}
			 catch (InterruptedException e) {
				// TODO Auto-generated catch block
				System.out.println(e.getMessage());
			}
		}
		
		this.moc.deleteClient(this.client.getNumber());	
		this.interrupt();
	}*/
	 @Override
	    public void onReceive(Object msg) throws Exception
	    {
		 	if(msg instanceof String)
		 	{
		 		String dataIn = (String) msg;
		 		if (dataIn.startsWith("Chat_")){

		            moc.tell(new SendToAllClients("Chat_"+this.client.getNick()+":"+dataIn.substring(5)),getSelf());
		 			}
		 		if(dataIn.startsWith("RejctPlayer_"))
		 		{System.out.println(dataIn);
		 			int i =-1;
		 			if(!startGame)
		 			{
		 			try{
		 				
		 			i = Integer.parseInt(dataIn.substring(12));
		 			}
		 			catch(NumberFormatException e)
		 			{
		 				//dataOut = "Error_invalid_playr_id";
		 			}
		 				moc.tell(new RejectPlayer(i,client.getNumber()), getSelf());
		 			}
		 			else
		 				send("Wait_");
		 		}
		 		if(startGame)
		 		{
		 			client.run(dataIn);
		 			
		 		}
		 		else{ 
		 		
		 			if(dataIn.startsWith("Name_"))
		 			{
		 					client.setNick(dataIn.substring(5));
		 					System.out.println("New Player's nick " + client.getNick());
		 					moc.tell(new RefreshClientsList(), getSelf());
		 				
		 			}
		 			else if(dataIn.startsWith("StartGame_"))
		 				{
		 					System.out.println("StartGame");
		 					this.client.ready();
		 						moc.tell(new StartGame(this.client.getNumber()), getSelf());
		 						

		 					
		 				}
		 		
		 			//vote:1 - reject, 0- not reject
		 			else if(dataIn.startsWith("reject_"))
		 			{
		 				
		 				int vote = 0;
		 				try{
		 					 vote = Integer.parseInt(dataIn.substring(7));
		 					 System.out.println("vote"+vote);
		 					}
		 					catch(NumberFormatException e)
		 					{
		 						//dataOut = "Error_invalid_playr_id";
		 					}
		 				if(client.rightToVote)
		 				{
		 					moc.tell( new Reject(vote), getSelf());
		 					client.rightToVote=false;
		 				}
		 			}
		 				
		 			else if(dataIn.startsWith("AddBot_"))
		 			{
		 			
		 					moc.tell(new AddBot(), getSelf());
		 			}
		 			if(dataIn.startsWith("ERROR_"))
		 			{
		 			    String Error =	dataIn.substring(6);
		 				System.err.println(dataIn.substring(6));
		 				if(Error == "Number")
		 				{
		 					send("Number_" + client.getNumber());
		 				}
		 				
		 			}

		 		}
		 			
		 	}
		 	else if(msg instanceof Info)
	            {        
	            	Info info = (Info) msg;             	
		            ObjectNode event = Json.newObject();
		            event.put("message", "[ "+ info.getName()+ " ] : " + info.getText()); 
		            
		            out.write(event);
	            }
		 	 
            /*if (msg instanceof Number)
            {   
            	int nr = ((Number) msg).getNumber();            	           			
            	String text = "I've got the number " + nr + " from WebSocket and send it to Table";
            	table.tell(new Info(text, name), getSelf()); 
            	table.tell(new Number(nr, name), getSelf());
            }  */
          /*  else if (msg instanceof Card)
            {
            	Card card = (Card) msg;    
            	String text = "I've got " + card.getRank() + " " + card.getColor() + " from Table" ;
            	table.tell(new Info(text, name), getSelf());  
            }     */       
            
		 	else
		 		unhandled(msg);
	            
	            
	        }  

}




